﻿/*
 * Summary:
 *   base class that provides indexer mechanism
 *   
 * History:
 *   Date           Author      Changes
 *   23/10/2010     YIWEI YU    Created
 */

using System;
using System.Collections;

namespace AcmeSportsStore
{
    class Indexer
    {
        protected ArrayList mArray = new ArrayList();

        protected IComparer mUniquenessBasedComparer;
        protected IComparer mFieldComparer;

        public Indexer(IComparer uniquenessBasedComparer,
            IComparer fieldComparer)
        {
            mUniquenessBasedComparer = uniquenessBasedComparer;
            mFieldComparer = fieldComparer;
        }

        public object this[int index]
        {
            get
            {
                return mArray[index];
            }

            set
            {
                mArray[index] = value;
            }
        }

        public int Count
        {
            get
            {
                return mArray.Count;
            }
        }

        public void Clear()
        {
            mArray.Clear();
        }

        /*
         * return the index to the object that is exactly
         * equal to 'objToFind'
         */
        public int GetIndex(object objToFind)
        {
            return mArray.BinarySearch(objToFind, 
                mUniquenessBasedComparer);
        }


        /*
         * return all the indices to the objects that have
         * the same value in the key field as 'objToFind'
         */
        public bool GetIndices(object objToFind, 
            out int first, out int count)
        {
            ArrayList result = new ArrayList();

            first = mArray.BinarySearch(objToFind, 
                mUniquenessBasedComparer);
            count = 0;

            if (first < 0)
            {
                return false;
            }

            for (int i = first; i < mArray.Count; i++)
            {
                object objCurrent = mArray[i];
                if (mFieldComparer.Compare(objCurrent, objToFind) == 0)
                {
                    count++;
                }
            }
            return (count > 0);
        }

        /*
         * return all the objects that have
         * the same value in the key field as 'objToFind'
         */
        public ArrayList GetItems(object objToFind)
        {
            int first;
            int count;
            bool exists = GetIndices(objToFind, out first, out count);

            ArrayList result = mArray.GetRange(first, count);

            return result;
        }

        public int Add(object objToAdd)
        {
            int index = GetIndex(objToAdd);
            if (index >= 0)
            {   // already exists
                return index;
            }

            index = -index - 1;

            mArray.Insert(index, objToAdd);

            return index;
        }

        public bool RemoveAt(int index)
        {
            if (index < 0 || index >= mArray.Count)
            {
                return false;
            }
            mArray.RemoveAt(index);
            return true;
        }

        public bool RemoveRange(int index, int count)
        {
            if (count <= 0 || index < 0 || index + count > mArray.Count)
            {
                return false;
            }
            mArray.RemoveRange(index, count);
            return true;
        }
    }
}
